package com.rojored.controls
{

import com.rojored.controls.plotClasses.PlotShaderBase;
import com.rojored.controls.plotClasses.SimplePlotShader;
import flash.display.Shader;
import mx.core.UIComponent;

/**
 *  Draws a plot chart.
 */
public class Plot extends UIComponent
{

    //--------------------------------------------------------------------------
    //
    //  Constructor
    //
    //--------------------------------------------------------------------------

    /**
     *  Constructor
     */
    public function Plot()
    {
        super();

        // Defaults
        shader = new SimplePlotShader();
        lineColor = 0xFFFFFF;
        lineAlpha = 1.0;
        lineThickness = 2;
        backgroundColor = 0x0000FF;
        backgroundAlpha = 1.0;
        minimum = 0;
        maximum = 300;
    }

    //--------------------------------------------------------------------------
    //
    //  Variables
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    private var lineColorAndAlphaDirty:Boolean;

    /**
     *  @private
     */
    private var backgroundColorAndAlphaDirty:Boolean;

    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------

    //--------------------------------------
    //  shader
    //--------------------------------------

    /**
     *  @private
     *  Storage for the shader property
     */
    private var _shader:PlotShaderBase;

    /**
     *  Shader used to draw the plot.
     */
    public function get shader():PlotShaderBase
    {
        return _shader;
    }

    /**
     *  @private
     */
    public function set shader(value:PlotShaderBase):void
    {
        if (_shader == value)
            return;

        _shader = value;

        lineColorAndAlphaDirty = true;
        backgroundColorAndAlphaDirty = true;
        invalidateProperties();
        invalidateDisplayList();
    }
    
    //--------------------------------------
    //  minimum 
    //--------------------------------------
    
    /**
     *  @private
     *  Storage for the minimum property
     */
    private var _minimum:Number;

    /**
     *  Minimum number expected on the data provider.
     */
    public function get minimum():Number
    {
        return _minimum;
    }

    /**
     *  @private
     */
    public function set minimum(value:Number):void
    {
        if (_minimum == value)
            return;

        _minimum = value;
        invalidateDisplayList();
    }
    
    //--------------------------------------
    //  maximum 
    //--------------------------------------
    
    /**
     *  @private
     *  Storage for the maximum property
     */
    private var _maximum:Number;

    /**
     *  Maximum number expected on the data provider.
     */
    public function get maximum():Number
    {
        return _maximum;
    }

    /**
     *  @private
     */
    public function set maximum(value:Number):void
    {
        if (_maximum == value)
            return;

        _maximum = value;
        invalidateDisplayList();
    }

    //--------------------------------------
    //  dataProvider
    //--------------------------------------

    /**
     *  @private
     *  Storage for the dataProvider property
     */
    private var _dataProvider:Vector.<Number>;

    /**
     *  Data points to plot.
     */
    public function get dataProvider():Vector.<Number>
    {
        return _dataProvider;
    }

    /**
     *  @private
     */
    public function set dataProvider(value:Vector.<Number>):void
    {
        if (_dataProvider == value)
            return;

        _dataProvider = value;
        invalidateDisplayList();
    }

    //--------------------------------------
    //  lineColor
    //--------------------------------------

    /**
     *  @private
     *  Storage for the lineColor property
     */
    private var _lineColor:uint;

    /**
     *  Color for the plot line.
     */
    public function get lineColor():uint
    {
        return _lineColor;
    }

    /**
     *  @private
     */
    public function set lineColor(value:uint):void
    {
        if (_lineColor == value)
            return;

        _lineColor = value;
        lineColorAndAlphaDirty = true;
        invalidateProperties();
        invalidateDisplayList();
    }

    //--------------------------------------
    //  lineAlpha
    //--------------------------------------

    /**
     *  @private
     *  Storage for the lineAlpha property
     */
    private var _lineAlpha:Number;

    /**
     *  Alpha for the plot line.
     */
    public function get lineAlpha():Number
    {
        return _lineAlpha;
    }

    /**
     *  @private
     */
    public function set lineAlpha(value:Number):void
    {
        if (_lineAlpha == value)
            return;

        _lineAlpha = value;
        lineColorAndAlphaDirty = true;
        invalidateProperties();
        invalidateDisplayList();
    }
    
    //--------------------------------------
    //  lineThickness 
    //--------------------------------------
    
    /**
     *  @private
     *  Storage for the lineThickness property
     */
    private var _lineThickness:Number;

    /**
     *  Line thickness in pixels.
     */
    public function get lineThickness():Number
    {
        return _lineThickness;
    }

    /**
     *  @private
     */
    public function set lineThickness(value:Number):void
    {
        if (_lineThickness == value)
            return;

        _lineThickness = value;
        invalidateDisplayList();
    }

    //--------------------------------------
    //  backgroundColor
    //--------------------------------------

    /**
     *  @private
     *  Storage for the backgroundColor property
     */
    private var _backgroundColor:uint;

    /**
     *  Color for the plot background.
     */
    public function get backgroundColor():uint
    {
        return _backgroundColor;
    }

    /**
     *  @private
     */
    public function set backgroundColor(value:uint):void
    {
        if (_backgroundColor == value)
            return;

        _backgroundColor = value;
        backgroundColorAndAlphaDirty = true;
        invalidateProperties();
        invalidateDisplayList();
    }

    //--------------------------------------
    //  backgroundAlpha
    //--------------------------------------

    /**
     *  @private
     *  Storage for the backgroundAlpha property
     */
    private var _backgroundAlpha:Number;

    /**
     *  Alpha for the plot backgroud.
     */
    public function get backgroundAlpha():Number
    {
        return _backgroundAlpha;
    }

    /**
     *  @private
     */
    public function set backgroundAlpha(value:Number):void
    {
        if (_backgroundAlpha == value)
            return;

        _backgroundAlpha = value;
        backgroundColorAndAlphaDirty = true;
        invalidateProperties();
        invalidateDisplayList();
    }

    //--------------------------------------------------------------------------
    //
    //  Overriden methods: UIComponent
    //
    //--------------------------------------------------------------------------

    /**
     *  @private
     */
    override protected function measure():void
    {
        super.measure();
        measuredWidth = 600;
        measuredHeight = 600;
    }

    /**
     *  @private
     */
    override protected function commitProperties():void
    {
        super.commitProperties();

        if (!shader)
            return;

        if (lineColorAndAlphaDirty)
        {
            lineColorAndAlphaDirty = false;
            shader.lineColor = lineColor;
            shader.lineAlpha = lineAlpha;
        }

        if (backgroundColorAndAlphaDirty)
        {
            backgroundColorAndAlphaDirty = false;
            shader.backgroundColor = backgroundColor;
            shader.backgroundAlpha = backgroundAlpha;
        }
    }

    /**
     *  @private
     */
    override protected function updateDisplayList(unscaledWidth:Number,
                                                  unscaledHeight:Number):void
    {
        super.updateDisplayList(unscaledWidth, unscaledHeight);
        graphics.clear();

        if (!shader)
            return;

        if (!dataProvider || !dataProvider.length)
        {
            graphics.beginFill(backgroundColor, backgroundAlpha);
        }
        else
        {
            shader.dataProvider = dataProvider;
            shader.minimum = minimum;
            shader.maximum = maximum;
            shader.lineThickness = lineThickness;
            shader.width = unscaledWidth;
            shader.height = unscaledHeight;
            graphics.beginShaderFill(Shader(shader));
        }

        graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
        graphics.endFill();
    }

    //--------------------------------------------------------------------------
    //
    //  Methods
    //
    //--------------------------------------------------------------------------

    /**
     *  Trigger a plot redraw.
     */
    public function redraw():void
    {
        invalidateDisplayList();
    }
}
}
